package com.huanshi.utils;

import com.huanshi.common.ResultCode;
import com.huanshi.exception.ServiceException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.security.Key;
import java.util.Date;
import java.util.List;

@Component
public class JwtTokenUtil {

  private static Logger log = LoggerFactory.getLogger(JwtTokenUtil.class);
  private static String secretKey;
  private static long jwtExpiration;

  @Value("${application.security.jwt.secret-key}")
  public void setSecretKey(String secretKey) {
    JwtTokenUtil.secretKey = secretKey;
  }

  @Value("${application.security.jwt.expiration}")
  public void setJwtExpiration(long jwtExpiration) {
    JwtTokenUtil.jwtExpiration = jwtExpiration;
  }

  /**
   * 解析jwt
   * @param jsonWebToken
   * @return
   */
  public static Claims parseJWT(String jsonWebToken) {
    try {
      return Jwts
              .parserBuilder()
              .setSigningKey(getSignInKey())
              .build()
              .parseClaimsJws(jsonWebToken)
              .getBody();
    } catch (ExpiredJwtException eje) {
      log.error("===== Token过期 =====", eje);
      throw new ServiceException(ResultCode.UNAUTHORIZED);
    }
//    catch (Exception e){
//      log.error("===== token解析异常 =====", e);
//      throw new ServiceException(ResultCode.VALIDATE_FAILED);
//    }
  }

  /**
   * 构建jwt
   * @param userId
   * @param username
   * @param role
   * @return
   */
  public static String createJWT(Long userId, String username, List<String> role) {
    try {

      //添加构成JWT的参数
      return  Jwts.builder()
              // 可以将基本不重要的对象信息放到claims
              .claim("role", role)
              .claim("userId", userId)
              .setSubject(username)           // 代表这个JWT的主体，即它的所有人
              .setIssuedAt(new Date(System.currentTimeMillis()))
              .setExpiration(new Date(System.currentTimeMillis() + jwtExpiration))
              .signWith(getSignInKey(), SignatureAlgorithm.HS256)
              .compact();
    } catch (Exception e) {
      log.error("签名失败", e);
      throw new ServiceException(ResultCode.FAILED);
    }
  }

  /**
   * 从token中获取用户名
   * @param token
   * @return
   */
  public static String getUsername(String token){
    String userName;
    try {
      final Claims claims = parseJWT(token);
      userName = claims.getSubject();
    }catch (Exception e){
      userName = null;
    }
    return userName;
  }

  /**
   * 从token中获取用户ID
   * @param token
   * @param base64Security
   * @return
   */
  public static Integer getUserId(String token){
    Integer userId;
    try {
      final Claims claims =  parseJWT(token);
      userId = (Integer) claims.get("userId");
    }catch (Exception e){
      log.error("", e);
      userId = null;
    }
    return userId;
  }

  /**
   * 是否已过期
   * @param token
   * @return
   */
  public static boolean isExpiration(String token) {
    final Date expiration = getExpirationDateFromToken(token);
    return expiration.before(new Date());
  }

  /**
   *
   * Description: 获取token过期时间
   * @param token
   */
  public static Date getExpirationDateFromToken(String token)
  {
    Date expiration;
    try {
      final Claims claims = parseJWT(token);
      expiration = claims.getExpiration();
    }catch (Exception e){
      expiration = null;
    }
    return expiration;
  }

  private static Key getSignInKey() {
    byte[] keyBytes = Decoders.BASE64.decode(secretKey);
    return Keys.hmacShaKeyFor(keyBytes);
  }

}